package com.hooper.iot.face.handler;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hooper.iot.constants.EventSource;
import com.hooper.iot.constants.MsgTypeConstants;
import com.hooper.iot.entity.CommonResponse;
import com.hooper.iot.entity.EventSoueceDto;
import com.hooper.iot.face.components.ChannelRepository;
import com.hooper.iot.util.IdUntil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;

import static io.netty.handler.codec.http.HttpUtil.isKeepAlive;
import static io.netty.handler.codec.http.HttpUtil.setContentLength;

/**
 * @ Copyright
 * @ Author     ：wangcheng.
 * @ Date       ：Created in 15:07 2022/4/27
 * @ Description：
 * @ Modified By：
 * @Version: $
 */
@Component(value = "noticeEventHandler")
@ChannelHandler.Sharable
@Slf4j
public class NoticeEventHandler extends ChannelInboundHandlerAdapter {
    @Resource(name = "channelRepository")
    private ChannelRepository channelRepository;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        if (msg instanceof FullHttpRequest) {

            handleHttpRequest(ctx, (FullHttpRequest) msg);


        } else if (msg instanceof WebSocketFrame) {
        }
        ctx.writeAndFlush("next");
        //交给下个处理器处理
//        ReferenceCountUtil.release(msg);
        ctx.fireChannelRead(msg);
    }

    private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
        // 如果 HTTP 解码失败, 返回HTTP异常
        if (!req.getDecoderResult().isSuccess() || (!"websocket".equalsIgnoreCase(req.headers().get("Upgrade")))) {
            //TODO 增加其他方式调用http实现控制人脸下发,由下个控制器去处理
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK));
            return;
        }
    }

    private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
        if (res.getStatus().code() == MsgTypeConstants.HTTP_STATUS_200) {
            if (req.headers().contains(MsgTypeConstants.MSG_TYPE) && req.headers().contains(MsgTypeConstants.REMOTE_HOST)) {
                JSONObject requestBody = JSONObject.parseObject(req.content().toString(CharsetUtil.UTF_8));
                Channel channel = channelRepository.get(req.headers().get(MsgTypeConstants.REMOTE_HOST));
                if (req.headers().get(MsgTypeConstants.MSG_TYPE).equals(MsgTypeConstants.SERVER_MESSAGE_SENT)) {
                    EventSoueceDto eventSoueceDto = new EventSoueceDto();
                    EventSoueceDto.Body body = eventSoueceDto.new Body();
                    eventSoueceDto.setCallBack(true);
                    eventSoueceDto.setDeviceId(requestBody.getString("deviceId"));
                    eventSoueceDto.setMsgId(IdUntil.getMessgeId());
                    eventSoueceDto.setMsgType(MsgTypeConstants.SERVER_MESSAGE_SENT);
                    //body
                    body.setEvent(requestBody.getString("event"));
                    body.setEventSource(EventSource.WEB);
                    body.setNoticeType(requestBody.getString("noticeType"));
                    body.setLevel(requestBody.getInteger("level"));
                    eventSoueceDto.setBody(Arrays.asList(body));
                    SerializerFeature[] arg = new SerializerFeature[]{SerializerFeature.WriteMapNullValue, SerializerFeature.QuoteFieldNames};
                    try {
                        channel.write(new TextWebSocketFrame(JSONObject.toJSONString(eventSoueceDto, arg)));
                        channel.flush();
                        ByteBuf buf = Unpooled.copiedBuffer(JSONObject.toJSONString(CommonResponse.success("消息下发成功！")), CharsetUtil.UTF_8);
                        res.content().writeBytes(buf);
                        buf.release();
                        setContentLength(res, res.content().readableBytes());
                    } catch (Exception e) {
                        log.info("远程控制失败====>" + e.toString());
                        ByteBuf buf = Unpooled.copiedBuffer(JSONObject.toJSONString(CommonResponse.failed("消息下发失败，设备不在线！")), CharsetUtil.UTF_8);
                        res.content().writeBytes(buf);
                        buf.release();
                        setContentLength(res, res.content().readableBytes());
                    }

                } else {
                    ByteBuf buf = Unpooled.copiedBuffer(JSONObject.toJSONString(CommonResponse.failed("未检测到远程控制相关参数！")), CharsetUtil.UTF_8);
                    res.content().writeBytes(buf);
                    buf.release();
                    setContentLength(res, res.content().readableBytes());
                    return;
                }
            } else {
                ByteBuf buf = Unpooled.copiedBuffer("error：请检查参数头是否包含msgType、remote-host信息", CharsetUtil.UTF_8);
                res.content().writeBytes(buf);
                buf.release();
                setContentLength(res, res.content().readableBytes());
            }
        }
        // 如果是非 Keep-Alive, 关闭连接
        ChannelFuture f = ctx.channel().writeAndFlush(res);
        if (!isKeepAlive(req) || res.getStatus().code() != 200) {
            f.addListener(ChannelFutureListener.CLOSE);
        }
    }
}
